package com.cn.learn.creator.advice;

import com.cn.learn.creator.annotation.Pagination;
import com.cn.learn.creator.domain.vo.ResultVO;
import com.cn.learn.creator.util.ReflectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

/**
 * @ClassName ServiceImplAdvice
 * @Description 服务层实现类的aop
 * @Author JiJiang
 * @Date 2023/7/13 16:30
 * @Version 1.0
 */
@Log4j2
@Aspect
@Component
public class ServiceImplAdvice {


    private static final String LIMIT = "limit";

    private static final int defaultLimitNum = 10;

    private static final String PAGE = "page";

    private static final int defaultPage = 1;


    //将带有 PermissionCheck 注解的类作为切点
    @Pointcut("@annotation(com.cn.learn.creator.annotation.Pagination)")
//    @Pointcut("@within(com.cn.wanxi.autoconfig.annotation.RequestLog)")
    public void pt_checkNeedPage() {

    }


    /**
     * 环绕通知
     * @param joinPoint
     * @return
     */
    @Around("pt_checkNeedPage()")
    // 会报警告：argNames attribute isn't defined。
    // 解决方法：@Before(value = "pointcut(apiLog)", argNames = "joinPoint,apiLog")
    public Object autoUsePageHelper(ProceedingJoinPoint joinPoint) {

        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();

        //获取需要被执行的方法对象
        Method method = methodSignature.getMethod();


        try {
            //获取方法注解
            Pagination listPageAnn = method.getAnnotation(Pagination.class);

            //如果方法上有注解
            if (listPageAnn != null) {

                //分页数、当前页索引
                int limit = defaultLimitNum, page = defaultPage;

                //携带limit 与 page 属性参数的索引
                int paramIndex = listPageAnn.pageParamIndex();

                Object[] args = joinPoint.getArgs();


                Object arg = null;
                //如果方法有入参并且参数索引正确
                if (args != null && args.length > paramIndex) {

                    Integer pageNum, pageSize;
                    //获取参数对象
                    arg = args[0];

                    pageNum = ReflectUtil.getProperty(arg, PAGE, Integer.TYPE);

                    pageSize = ReflectUtil.getProperty(arg, LIMIT, Integer.TYPE);

                    page = (Objects.isNull(pageNum) || pageNum < 1) ? defaultPage : pageNum;

                    limit = (Objects.isNull(pageSize)) ? defaultLimitNum : pageSize;

                }
                //开启分页
                PageHelper.startPage(page, limit);
            }


            //执行被增强的方法
            Object result = joinPoint.proceed();

            //如果方法上有注解
            if (listPageAnn != null) {


                //TODO 优化为策略设计模式
                //如果返回的对象为ResultVO类的实例
                if (result instanceof ResultVO) {


                    ResultVO retData = (ResultVO) result;


                    Object data = retData.getData();

                    //如果返回的数据类型为集合
                    if (data instanceof List) {

                        List dataList = (List) data;

                        PageInfo pageInfo = new PageInfo(dataList);
                        int count = (int) pageInfo.getTotal();
                        retData.setCount(count);
                    }
                }
            }
            return result;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

        return ResultVO.getResult(1, "服务器异常", 0, null);

    }


}
